package api

import (
	"bytes"
	"encoding/json"
	"errors"
	"fmt"
	"io/ioutil"
	"log"
	"net/http"
	"wechat/gpt/client/conf"
)

const (
	baseUrl = "https://api.openai.com/v1/"
)

var (
	httpClient *http.Client
)

func init() {
	httpClient = &http.Client{}
}

type apiRequest struct {
	Model            string  `json:"model"`
	Prompt           string  `json:"prompt"`
	MaxTokens        int     `json:"max_tokens"`
	Temperature      float32 `json:"temperature"`
	TopP             int     `json:"top_p"`
	FrequencyPenalty int     `json:"frequency_penalty"`
	PresencePenalty  int     `json:"presence_penalty"`
}

type apiResponse struct {
	ID      string                 `json:"id"`
	Object  string                 `json:"object"`
	Created int                    `json:"created"`
	Model   string                 `json:"model"`
	Choices []choiceItem           `json:"choices"`
	Usage   map[string]interface{} `json:"usage"`
}

type choiceItem struct {
	Text         string `json:"text"`
	Index        int    `json:"index"`
	Logprobs     int    `json:"logprobs"`
	FinishReason string `json:"finish_reason"`
}

func Call(msg string) (string, error) {

	// 构建请求体
	req := apiRequest{
		Model:            "text-davinci-003",
		Prompt:           msg,
		MaxTokens:        1024,
		Temperature:      0.7,
		TopP:             1,
		FrequencyPenalty: 0,
		PresencePenalty:  0,
	}

	// 将请求体转换为json形式
	reqJson, err := json.Marshal(req)
	if err != nil {
		return "", err
	}

	log.Printf("send to chatgpt : %v", string(reqJson))

	httpRequest, err := http.NewRequest("POST", baseUrl+"completions", bytes.NewBuffer(reqJson))
	if err != nil {
		return "", err
	}

	// 请求头中设置api_key
	apiKey := conf.GetConfig().ApiKey
	httpRequest.Header.Set("Content-Type", "application/json")
	httpRequest.Header.Set("Authorization", "Bearer "+apiKey)

	// 发起请求
	httpResponse, err := httpClient.Do(httpRequest)
	if err != nil {
		return "", err
	}

	// 关闭io
	defer httpResponse.Body.Close()
	if httpResponse.StatusCode != 200 {
		return "", errors.New(fmt.Sprintf("api status code not 200, code : %d", httpResponse.StatusCode))
	}

	// 读取响应体数据
	body, err := ioutil.ReadAll(httpResponse.Body)
	if err != nil {
		return "", err
	}

	// 构建响应体
	apiResp := &apiResponse{}

	log.Println(string(body))

	// 反序列化响应数据
	err = json.Unmarshal(body, apiResp)
	if err != nil {
		return "", err
	}

	// 选取最终结果
	var res string
	if len(apiResp.Choices) > 0 {
		res = apiResp.Choices[0].Text
	}
	log.Printf("received from chatgpt : %s \n", res)

	return res, nil
}
